package com.sptus.web.util;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.sptus.common.utils.BrowserUtils;
import com.sptus.common.utils.SpringContextUtils;
import com.sptus.common.utils.ip.IpUtils;
import com.sptus.framework.service.BaseCommonService;
import com.sptus.framework.mqtt.MyMqttClient;
import com.sptus.system.domain.DevDictionaries;
import com.sptus.system.dto.LogDTO;
import com.sptus.system.enums.ClientTerminalTypeEnum;
import org.mariuszgromada.math.mxparser.Expression;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.StringUtils;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.servlet.http.HttpServletRequest;
import java.text.DecimalFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class DevSqlUtil {

    HashMap<String,String> keyContrast;


    public HashMap<String,String> keyContrast(String key){
        keyContrast.put("s1","DGV");
        return keyContrast;
    }

//    public getList(){
//
//    }

    public static List<DevDictionaries> DevDataSql(List<DevDictionaries> devDictionaries, JdbcTemplate jdbcTemplate, String sn) {

//        Map<String, Set<String>> collect = devDictionaries.stream().collect(Collectors.groupingBy(DevDictionaries::getRelevanceTable, Collectors.mapping(DevDictionaries::getCode, Collectors.toSet())));
        Map<String, Set<String>> collect1 = devDictionaries.stream().filter(e->e.isOpe()==true).collect(Collectors.groupingBy(DevDictionaries::getRelevanceTable, Collectors.mapping(DevDictionaries::getCode, Collectors.toSet())));

        Set<String> strings = collect1.keySet();

        String left = "";
        StringBuffer tables = new StringBuffer();
        StringBuffer columns = new StringBuffer();
        for (String string : strings) {

            Set<String> column = collect1.get(string);
            for (String s : column) {
                columns.append("," + s);
            }
            if (StringUtils.isEmpty(tables.toString())) {
                tables.append(string + "");
            } else {
                tables.append(" left join " + string + " on " + left + ".sn =" + string + ".sn ");
            }
            left = string;
        }
        if (!StringUtils.isEmpty(sn)) {
            tables.append(" where " + left + ".sn=" + sn);
        }
        String substring = columns.toString().substring(1);

        Map<String, Object> data = new HashMap<>();
        try {
            System.out.println("select " + substring + " from " + tables.toString());
            data = jdbcTemplate.queryForMap("select " + substring + " from " + tables.toString());
            for (DevDictionaries devDictionary : devDictionaries) {
                String code = devDictionary.getCode();
                if (data.get(code) != null) {
                    devDictionary.setValue(data.get(code).toString());
                }
            }
        } catch (Exception e) {
            devDictionaries = new ArrayList<>();
        } finally {

        }
        valueCompute(devDictionaries);
        return devDictionaries;

    }
    public static List<DevDictionaries> DevDataHistorySql(List<DevDictionaries> devDictionaries, String startTime, String endTIme, JdbcTemplate jdbcTemplate, String sn) {
        return DevDataHistorySql(devDictionaries,startTime,endTIme,jdbcTemplate,sn,"");
    }
    public static List<DevDictionaries> DevDataHistorySql(List<DevDictionaries> devDictionaries, JdbcTemplate jdbcTemplate, String sql) {
        List<Map<String, Object>> data =new ArrayList<>();
        try {
            data = jdbcTemplate.queryForList(sql);
            Map<String, List<String>> convert = convert(data);
            devDictionaries.forEach(e->{
                e.setValues( convert.get(e.getCode()));
            });
        } catch (Exception e) {
            devDictionaries = new ArrayList<>();
        } finally {
        }
//        valueCompute(devDictionaries);
        return devDictionaries;

    }
    public static List<DevDictionaries> DevDataHistorySql(List<DevDictionaries> devDictionaries, String startTime, String endTIme, JdbcTemplate jdbcTemplate, String sn, String pj) {

      Map<String, Set<String>> collect = devDictionaries.stream().filter(e->e.isOpe()==true).collect(Collectors.groupingBy(DevDictionaries::getRelevanceTable, Collectors.mapping(DevDictionaries::getCode, Collectors.toSet())));
        Map<String, DevDictionaries> open = devDictionaries.stream().filter(e->e.isOpe()==true).collect(Collectors.toMap(DevDictionaries::getCode, Function.identity()));

        Set<String> strings = collect.keySet();

        String left = "";
        StringBuffer tables = new StringBuffer();
        StringBuffer columns = new StringBuffer();
        for (String string : strings) {

            Set<String> column = collect.get(string);
            for (String s : column) {
                String operation = open.get(s).getOperation();
                if(!StringUtils.isEmpty(operation)){
                    columns.append(", ROUND("+ s+operation.replace("x","")+", 1) "+s);
                }else {
                    columns.append("," + s);
                }
            }
            if (StringUtils.isEmpty(tables.toString())) {
                tables.append(string + "");
            } else {
                tables.append(" left join " + string + " on " + left + ".sn =" + string + ".sn ");
            }
            left = string;
        }
        if (!StringUtils.isEmpty(sn)) {
            tables.append(" where " + left + ".sn=" + sn);
            tables.append( " and " +left +".create_time" +" between '" +startTime+"' and '"+endTIme+"'" );

        }
        if (!StringUtils.isEmpty(pj)) {
            tables.append( " "+pj );
        }

        String substring = columns.toString().substring(1);
        List<Map<String, Object>> data =new ArrayList<>();
        try {
            System.out.println("select " + substring + " from " + tables.toString());
            data = jdbcTemplate.queryForList("select " + substring + " from " + tables.toString());
            Map<String, List<String>> convert = convert(data);
            devDictionaries.forEach(e->{
                e.setValues( convert.get(e.getCode()));
            });


        } catch (Exception e) {
            devDictionaries = new ArrayList<>();
        } finally {

        }
//        valueCompute(devDictionaries);
        return devDictionaries;

    }


    public static Map<String, List<String>> convert(List<Map<String, Object>> input) {
      HashMap<String, Object> stringObjectHashMap = new HashMap<>();
        Map<String, List<String>> result = new HashMap<>();

        for (Map<String, Object> stringObjectMap : input) {
            Set<String> key = stringObjectMap.keySet();
            key.forEach(e->{
                if(result.containsKey(e)){
                    result.get(e).add(stringObjectMap.get(e)+"");
                }else {
                    List<String> list = new ArrayList<>();
                    list.add(stringObjectMap.get(e)+"");
                    result.put(e,list);
                }
            });
        }
        return result;
    }

    public static void setDevParameters(String code, String value, String mac, String sn, BaseCommonService baseCommonService, String id, String name) {



        if (code.equals("MD")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.MDMode());
            value = setParamContext.executeStrategy(value);
        }
        //led 待机
        else if (code.equals("LST")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.LSTMode());
            value = setParamContext.executeStrategy(value);
        }
        //静音
        else  if (code.equals("BZ")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.BZMode());
            value = setParamContext.executeStrategy(value);
        }
        //外部CT功能
        else if (code.equals("ECTS")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.ECTSMode());
            value = setParamContext.executeStrategy(value);
        }
        else if (code.equals("RAPIDEN")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.RAPIDENMode());
            value = setParamContext.executeStrategy(value);
        }else if (code.equals("MO")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.MOMode());
            value = setParamContext.executeStrategy(value);
        }
        else if (code.equals("FO")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.FOMode());
            value = setParamContext.executeStrategy(value);
        }
        else if (code.equals("OV")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.OVMode());
            value = setParamContext.executeStrategy(value);
        }
        else if (code.equals("BFE1")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.BFE1Mode());
            value = setParamContext.executeStrategy(value);
        }

        else if (code.equals("BFE2")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.BFE2Mode());
            value = setParamContext.executeStrategy(value);
        }else if (code.equals("PDE2")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.PDE2Mode());
            value = setParamContext.executeStrategy(value);
        }

        else if (code.equals("PDE1")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.PDE1Mode());
            value = setParamContext.executeStrategy(value);
        }
        else if (code.equals("FE")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.FEMode());
            value = setParamContext.executeStrategy(value);
        }
        else  if (code.equals("RL")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.MDMode());
            value = setParamContext.executeStrategy(value);
        }
        else if (code.equals("TSL")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.TSLMode());
            value = setParamContext.executeStrategy(value);
        }
        else  if (code.equals("OPANG")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.OPANGMode());
            value = setParamContext.executeStrategy(value);
        }
        else if (code.equals("SP")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.SPMode());
            value = setParamContext.executeStrategy(value);
        }
        else if (code.equals("PVP")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.PVPMode());
            value = setParamContext.executeStrategy(value);
        }
        else if (code.equals("MCG")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.MCGMode());
            value = setParamContext.executeStrategy(value);
        } else if (code.equals("MCC")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.MCCMode());
            value = setParamContext.executeStrategy(value);
        }
        else if (code.equals("MDH")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.MDHMode());
            value = setParamContext.executeStrategy(value);
        }
        else if (code.equals("TS1")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.TS1Mode());
            value = setParamContext.executeStrategy(value);
        }
        else if (code.equals("T")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.TMode());
            value = setParamContext.executeStrategy(value);
        }
        else if (code.equals("OTA")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.OTAMode());
            value = setParamContext.executeStrategy(value+","+sn);
        }
        else if (code.equals("UF")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.UFMode());
            value = setParamContext.executeStrategy(value);
        }
        else if (code.equals("BT")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.BTMode());

            value = setParamContext.executeStrategy(value);
        }else if (code.equals("PCE")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.PCEMode());
            value = setParamContext.executeStrategy(value);

        }else if (code.equals("BBA")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.BBAMode());
            value = setParamContext.executeStrategy(value);

        }else if (code.equals("GENP")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.GENPMode());
            value = setParamContext.executeStrategy(value);

        }
        else if (code.equals("VO")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.VOMode());
            value = setParamContext.executeStrategy(value);

        } else if (code.equals("OM")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.OMMode());
            value = setParamContext.executeStrategy(value);

        }else if (code.equals("GGI")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.GGIMode());
            value = setParamContext.executeStrategy(value);

        }else if (code.equals("WGI")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.WGIMode());
            value = setParamContext.executeStrategy(value);

        }
        else if (code.equals("BSOC1")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.BSOC1Mode());
            value = setParamContext.executeStrategy(value);

        }
        else if (code.equals("BVF")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.BVFMode());
            value = setParamContext.executeStrategy(value);

        }
        else if (code.equals("LOG")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.LOGMode());
            value = setParamContext.executeStrategy(value);

        }
        else if (code.equals("BVM")) {
            SetParamContext setParamContext = new SetParamContext(new SetParamStrategy.BVMMode());
            value = setParamContext.executeStrategy(value);

        }
        HashMap<String, String> map = new HashMap<>();
        if(value.split(":").length>1){
            for (int i = 0; i < value.split(":").length; i++) {
                map.put(code+i,value.split(":")[i]);
            }
        }else {
            map.put(code,value);
        }
        if(!code.equals("OTA")){
            map.put("SKEY",System.currentTimeMillis()+"");
        }
        String jsonString = JSONObject.toJSONString(map);
        MyMqttClient.publishMessage("/" + mac + "/Rtesttopic", jsonString, 1);
        //添加设置日志
        LogDTO sysLog=new LogDTO();
        sysLog.setId(String.valueOf(IdWorker.getId()));
        //注解上的描述,操作日志内容
        sysLog.setLogContent("设置设备："+sn+"" +"code:"+ code+" msg:"+value);
        sysLog.setLogType(2);
        sysLog.setOperateType(2);
        sysLog.setUserid(id);
        sysLog.setUsername(name);
        sysLog.setClientType(ClientTerminalTypeEnum.APP.getKey());
        try {
            //获取request
            HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
            //设置IP地址
            sysLog.setIp(IpUtils.getIpAddr(request));

            try {
                //设置客户端
                if(BrowserUtils.isDesktop(request)){
                    sysLog.setClientType(ClientTerminalTypeEnum.PC.getKey());
                }else{
                    sysLog.setClientType(ClientTerminalTypeEnum.APP.getKey());
                }
            } catch (Exception e) {
                //e.printStackTrace();
            }
        } catch (Exception e) {
            sysLog.setIp("127.0.0.1");
        }
        baseCommonService.addLog(sysLog);
    }

    /**
     * 将JavaScript数学表达式转换为mxParser支持的语法
     */
    private static String convertJsToMxParserSyntax(String originalExpr) {
        return originalExpr
                .replace("Math.", "")
                .replace("pow(", "pow(")    // pow(x,y) -> x^y
                .replace("toFixed(", "round(");
    }

    /**
     * 格式化结果，完全匹配Nashorn的输出风格
     */
    private static String formatResult(double result) {
        if (Double.isInfinite(result)) {
            return result > 0 ? "Infinity" : "-Infinity";
        }
        return result == (long)result ?
                String.valueOf((long)result) :  // 整数去掉.0
                String.valueOf(result);         // 保留小数
    }

    public static List<DevDictionaries> valueCompute(List<DevDictionaries> devDictionaries) {
        devDictionaries.forEach(e -> {
            //                if (!StringUtils.isEmpty(e.getOperation())) {
//                    if (!StringUtils.isEmpty(e.getValue())) {
//                        String x = e.getOperation().replace("x", e.getValue());
//                        ScriptEngine jse = new ScriptEngineManager().getEngineByName("nashorn");
//                        e.setValue(jse.eval(x) + "");
//                    }
//                }
            if (!StringUtils.isEmpty(e.getOperation())) {
                // 1. 转换表达式格式（兼容JS函数写法）
                String convertedExpr = convertJsToMxParserSyntax(e.getOperation());

                // 2. 替换变量x为实际值
                String finalExpr = convertedExpr.replace("x", e.getValue());

                // 3. 获取可复用的表达式实例
                Expression exp = new Expression();
                exp.setSilentMode(); // 禁用 mxParser 的默认错误打印
                exp.setExpressionString(finalExpr);

                // 4. 执行计算（保持与原代码相同的静默失败逻辑）
                if (exp.checkSyntax()) {
                    double result = exp.calculate();
                    e.setValue(formatResult(result)); // 保持与原代码相同的字符串输出格式
                }
            }
            if (!StringUtils.isEmpty(e.getAnalysis())) {
                JSONObject parse = JSONObject.parseObject(e.getAnalysis());
                String valid = parse.getString("valid");
                String aggregate = parse.getString("aggregate");
                String replace = parse.getString("replace");
                if (!StringUtils.isEmpty(valid)) {
                    int i = Integer.parseInt(valid);
                    String xs = "";
                    for (int j = 0; j < i; j++) {
                        xs += "0";
                    }
                    double v = Double.parseDouble(e.getValue());
                    DecimalFormat df = new DecimalFormat("#0." + xs); // 保留两位小数
                    e.setValue(df.format(v));
                }
                if (!StringUtils.isEmpty(aggregate)) {
                    String[] split = e.getValue().split(aggregate);
                    int i=0;
                    for (String s : split) {
                        i+=Integer.parseInt(s);
                    }
                    e.setValue(i+"");
                }
                if (!StringUtils.isEmpty(replace)) {
                    JSONObject jsonObject = JSONObject.parseObject(replace);
                    e.setValue(jsonObject.getString(e.getValue()));
                }
            }
        });
        return devDictionaries;
    }

    public static void main(String[] args) {
        DecimalFormat df = new DecimalFormat("#0.0" ); // 保留两位小数
        System.out.println(df.format(100));

    }


}
